(function (window, undefined) {
  let enemyCampLife = document.getElementById("enemy").children[0];
  let playerScore = document.getElementById("player").children[0].children[0];
  let playerTankLife = document.getElementById("player").children[1].children[0];
  let playerCampLife = document.getElementById("player").children[2].children[0];
  //记录玩家坦克实时位置
  let playerRangeLeft = 0;
  let playerRangeRight = 0;
  let playerRangeTop = 0;
  let playerRangeBottom = 0;
  var that;
  //坦克角度对应方向映射对象
  var directionMap = { "-90": "left", 0: "top", 90: "right", 180: "bottom" };
  function Game() {
    this.map = map;
    this.player = new Player({
      bodyColor: "#fafafa",
      headColor: "red",
      isBelong: "player",
      direction: -90,
    });
    this.enemy = new Enemy();
    //游戏生成的NPC子弹实例
    this.enemyBullet = new Bullet();
    //玩家子弹实例
    this.playerBullet = new Bullet({
      color: "red",
      isBelong: "player",
    });
    this.playerCamp = new BaseCamp({
      campColor: "#fafafa",
      centerColor: "red",
      isBelong: "player",
    });
    this.enemyCamp = new BaseCamp();
    that = this;
  }
  Game.prototype.start = function () {
    this.player.render(this.map);
    this.playerCamp.render(this.map);
    this.enemyCamp.render(this.map);
    this.enemy.createEnemy(this.map);
    this.enemy.createEnemy(this.map);
    this.enemy.createEnemy(this.map);
    enemyCampLife.innerText = this.enemyCamp.life;
    playerScore.innerText = this.player.grade;
    playerTankLife.innerText = this.player.life;
    playerCampLife.innerText = this.playerCamp.life;
    // this.enemy.render(this.map);
    bindKeycode();
    moveEnemyTankAutomatic();
    changeEnemyTankDirection();
  };
  //移动坦克
  function moveTank(newDirection, oldDirection) {
    // 非同向先转向
    if (newDirection !== oldDirection) {
      that.player.direction = newDirection;
      that.player.remove(that.map);
      that.player.render(that.map);
    } else {
      //即将超出地图或碰撞玩家或敌人营地，停止当前方向的运动
      if (judgOverMap(that.player.tankBox)) return;
      that.player.remove(that.map);
      that.player.move();
      that.player.render(that.map);
      // console.dir(that.player.tankElements[0]);
      recordPlayerTankPosition(that.player.tankBox);
    }
  }
  function recordPlayerTankPosition(tank) {
    playerRangeLeft = tank.offsetLeft;
    playerRangeRight = playerRangeLeft + tank.clientWidth;
    playerRangeTop = tank.offsetTop;
    playerRangeBottom = playerRangeTop + tank.clientHeight;
  }
  var enemyMoveTimer = null;
  //NPC自动移动
  function moveEnemyTankAutomatic() {
    enemyMoveTimer = setInterval(() => {
      for (let item of that.enemy.tankElements) {
        item.style.transform = "rotate(" + item.customDirection + "deg)";
        if (judgOverMap(item)) {
          item.customDirection = getRandomAngle();
          continue;
        }
        switch (item.customDirection) {
          case -90:
            item.style.left = item.offsetLeft - 20 + "px";
            break;
          case 0:
            item.style.top = item.offsetTop - 20 + "px";
            break;
          case 90:
            item.style.left = item.offsetLeft + 20 + "px";
            break;
          case 180:
            item.style.top = item.offsetTop + 20 + "px";
            break;
          default:
            break;
        }
        fireBullet(
          {
            x: item.offsetLeft,
            y: item.offsetTop,
            direction: directionMap[item.customDirection],
          },
          "enemyBullet"
        );
      }
    }, 2000);
  }
  //改变NPC移动方向
  function changeEnemyTankDirection() {
    setInterval(() => {
      let index = Tools.getRandom(0, that.enemy.tankElements.length - 1);
      // console.log(index);
      that.enemy.tankElements[index].customDirection = getRandomAngle();
    }, 6000);
  }
  //获取NPC随机移动角度
  function getRandomAngle() {
    return [-90, 0, 90, 180][Tools.getRandom(0, 3)];
  }
  //判断坦克移动是否移动超出地图或碰撞到营地（左上，右下九宫格区域）
  function judgOverMap(tank) {
    // console.log(tank.offsetLeft, tank.offsetTop, tank.clientWidth, tank.clientHeight);
    //1，判断是否碰撞到营地
    //注：一个坦克宽等于3倍格子宽， 一个格子默认宽高 20x20
    /* 
    1.1 左上角营地范围：top: 0~2, left: 0~2
    1.2 右下角营地范围：top:0 ~ map.clientHeight - 6倍高 ,left: 0 ~ map.clientWidth - 6 倍宽
    */
    /* 1.1 
   条件1：左偏移小于3倍格子宽以及offsetTop <= 2倍格子；
   条件2：上偏移小于3倍格子高以及offsetLeft <= 2倍格子；
    */
    if (
      (tank.offsetLeft <= tank.clientWidth && tank.offsetTop <= (tank.clientHeight / 3) * 2 && tank.customDirection === -90) ||
      (tank.offsetTop <= tank.clientHeight && tank.offsetLeft <= (tank.clientWidth / 3) * 2 && tank.customDirection === 0)
    ) {
      console.log("1.1");
      return true;
    }
    /* 1.2
   条件1：左偏移地图宽减去6倍格子宽以及offsetTop = map.clientHeight - 5倍格子高；
   条件2：上偏移地图高减去6倍格子高以及offsetLeft = map.clientWidth - 5倍格子宽；
   */
    if (
      (tank.offsetLeft >= that.map.clientWidth - 2 * tank.clientWidth &&
        tank.offsetTop >= that.map.clientHeight - (tank.clientHeight / 3) * 5 &&
        tank.customDirection === 90) ||
      (tank.offsetTop >= that.map.clientHeight - 2 * tank.clientHeight &&
        tank.offsetLeft >= that.map.clientWidth - (tank.clientWidth / 3) * 5 &&
        tank.customDirection === 180)
    ) {
      console.log("1.2");
      return true;
    }
    //2, 判断是否超出地图范围
    /* 
    坦克的位置： offsetLeft <=0, offsetTop <=0, 
    或超出地图最大宽， 高 
    */
    if (
      (tank.offsetLeft <= 0 && tank.customDirection === -90) ||
      (tank.offsetLeft >= that.map.clientWidth - tank.clientWidth && tank.customDirection === 90) ||
      (tank.offsetTop <= 0 && tank.customDirection === 0) ||
      (tank.offsetTop >= that.map.clientHeight - tank.clientHeight && tank.customDirection === 180)
    ) {
      console.log("2.1");
      return true;
    }
    // console.log(that.map.clientWidth, that.map.clientHeight);
    //下一次运动不会碰撞
    return false;
  }
  //绑定键值
  function bindKeycode() {
    document.onkeydown = function (e) {
      // console.log(e.keyCode);
      //通过按键的值，判断坦克的转向方向，将坦克坦克看作一个整体
      //(默认)方向top, rotate: 0;
      //方向left, rotate: -90;
      //方向right, rotate: 90;
      //方向bottom, rotate: 180;
      //默认坦克实例初始化角度为0
      switch (e.keyCode) {
        case 37:
          moveTank(-90, that.player.direction);
          break;
        case 38:
          moveTank(0, that.player.direction);
          break;
        case 39:
          moveTank(90, that.player.direction);
          break;
        case 40:
          moveTank(180, that.player.direction);
          break;
        //发射子弹, Q键
        case 81:
          fireBullet({
            x: that.player.tankBox.offsetLeft,
            y: that.player.tankBox.offsetTop,
            direction: directionMap[that.player.direction],
          });
          break;
        default:
          break;
      }
    };
  }
  //NPC或玩家射击子弹
  function fireBullet(option, bullet = "playerBullet") {
    //根据不同方向补充生成小球位置偏移量
    /* 
    原因：计算小球初始化位置时参考玩家实例偏移坐标,
    为了模拟玩家攻击发出子弹时从炮口发出，故对子弹初始位置进行部分修正
    */
    switch (option.direction) {
      case "left":
        option.y += 20;
        break;
      case "top":
        option.x += 20;
        break;
      case "right":
        option.x += 60;
        option.y += 20;
        break;
      case "bottom":
        option.x += 20;
        option.y += 60;
        break;
      default:
        break;
    }
    // console.log(bullet, that[bullet]);
    that[bullet].x = option.x;
    that[bullet].y = option.y;
    that[bullet].direction = option.direction;
    that[bullet].render(that.map);
    // that[bullet].move(that.map);
    let currentBullet = bullet;
    //NPC发射子弹： 检测玩家坦克或营地是否被击中
    //玩家发射子弹： 检测NPC坦克或营地是否被击中
    let currentTankElement = that[bullet === "playerBullet" ? "enemy" : "player"].tankElements;
    let currentCampElement = that[bullet === "playerBullet" ? "enemyCamp" : "playerCamp"].campElements;
    // console.log(currentTankElement);
    moveBullet(that.map, currentBullet, currentTankElement, currentCampElement);
  }
  //全局定时器, NPC 和 玩家
  var timerObj = {
    playerBullet: null, //玩家
    enemyBullet: null, //NPC
  };
  //子弹移动，定时移动
  function moveBullet(map, bullet, tankElementsArr, campElement) {
    let maxWidth = map.clientWidth;
    let maxHeight = map.clientHeight;
    // console.log("tank", tankElementsArr);
    // console.log("camp", campElement);
    //已有定时器，不再开启
    if (timerObj[bullet]) return;
    // console.log(this.bulletElements);
    //子弹一旦创建，即沿着初始移动的方向知道碰到其他坦克，阵营中心，超出地图范围，则删除该子弹实体
    timerObj[bullet] = setInterval(() => {
      //给外部循环添加标签， 当子弹击中目标跳过该次循环
      outLoop: for (let i = 0; i < that[bullet].bulletElements.length; i++) {
        //根据各个元素初始方向持续运动
        let item = that[bullet].bulletElements[i];
        let moveDirection = item.customDirection;
        switch (moveDirection) {
          case "left":
            item.style.left = item.offsetLeft - 20 + "px";
            break;
          case "top":
            item.style.top = item.offsetTop - 20 + "px";
            break;
          case "right":
            item.style.left = item.offsetLeft + 20 + "px";
            break;
          case "bottom":
            item.style.top = item.offsetTop + 20 + "px";
            break;
          default:
            break;
        }
        if (item.offsetLeft < 0 || item.offsetLeft >= maxWidth || item.offsetTop < 0 || item.offsetTop >= maxHeight) {
          map.removeChild(item);
          //将运动出局的子弹先置空，避免改变元素顺序，后续进行清除
          // console.log(null);
          that[bullet].bulletElements[i] = null;
          continue outLoop;
          // this.bulletElements.splice(i, 1);
        }
        //子弹未出局，进行下一步判断
        if (item !== null) {
          // console.dir(tankElementsArr, campElement);
          for (let j = 0; j < tankElementsArr.length; j++) {
            // console.log("m1");
            // console.dir(m1);
            if (judgFired(tankElementsArr[j], item, j)) {
              map.removeChild(item);
              that[bullet].bulletElements[i] = null;
              // console.log(that[bullet].bulletElements);
              //子弹击中敌对阵营坦克，停止循环
              //击中目标，跳过本次循环
              continue outLoop;
            }
          }
          for (let k = 0; k < campElement.length; k++) {
            // console.log("m2");
            // console.dir(m2);
            if (judgFired(campElement[k], item)) {
              map.removeChild(item);
              that[bullet].bulletElements[i] = null;
              //击中目标，跳过本次循环
              continue outLoop;
            }
          }
        }
      }
      //将出局置空元素清除
      that[bullet].bulletElements = that[bullet].bulletElements.filter((m) => m !== null);
      // console.log(that[bullet].bulletElements);
      if (that[bullet].bulletElements.length === 0) {
        clearInterval(timerObj[bullet]);
        timerObj[bullet] = null;
      }
    }, 150);
  }
  /* 
  子弹击中玩家或者营地
  1，击中营地，被击中方阵营生命值减一；
  2，击中NPC, 被击中NPC死亡， 并且需要重新生成一个NPC， 同时玩家积分加一
  3, 击中玩家， 被击中玩家生命值减一（玩家生命值3）

  */
  var fireConditionMethods = {
    "tank-player": () => {
      that.player.life -= 1;
      playerTankLife.innerText = that.player.life;
    },
    "tank-NPC": (index) => {
      that.enemy.remove(that.map, index);
      that.enemy.createEnemy(that.map);
      that.player.grade += 1;
      playerScore.innerText = that.player.grade;
    },
    "camp-player": () => {
      that.playerCamp.life -= 1;
      playerCampLife.innerText = that.playerCamp.life;
    },
    "camp-NPC": () => {
      that.enemyCamp.life -= 1;
      enemyCampLife.innerText = that.enemyCamp.life;
    },
  };
  //子弹是否击中玩家或NPC或某个阵营
  function judgFired(judgObj, bullet, index = null) {
    // console.log(judgObj.customBelong, bullet.customBelong);
    // 首先判断判断对象在地图中的所占范围
    let rangeLeft = judgObj.customBelong === "player" && judgObj.customRole === "tank" ? playerRangeLeft : judgObj.offsetLeft;
    let rangeRight = judgObj.customBelong === "player" && judgObj.customRole === "tank" ? playerRangeRight : rangeLeft + judgObj.clientWidth;
    let rangeTop = judgObj.customBelong === "player" && judgObj.customRole === "tank" ? playerRangeTop : judgObj.offsetTop;
    let rangeBottom = judgObj.customBelong === "player" && judgObj.customRole === "tank" ? playerRangeBottom : rangeTop + judgObj.clientHeight;
    // console.log(rangeLeft, rangeRight, rangeTop, rangeBottom);
    // console.log(bullet.offsetLeft, bullet.offsetTop);
    //子弹出现在阵营或坦克实例范围中，该对象被击中， 击中：是
    if (bullet.offsetLeft >= rangeLeft && bullet.offsetLeft <= rangeRight && bullet.offsetTop >= rangeTop && bullet.offsetTop <= rangeBottom) {
      // console.log(12345);
      //子弹，阵营或坦克所属相同，击中：否
      if (judgObj.customBelong === bullet.customBelong) {
        // console.log("否");
        return false;
      }
      fireConditionMethods[judgObj.customRole + "-" + judgObj.customBelong](index);
      bullet = null;
      judgGameOver();
      // console.log("是");
      return true;
    }
    //将被击中者所属类型和所属阵营拼接作为对象键值当作条件判断，简化if判断
    // console.log("否");
    // 击中：否
    return false;
  }
  /* 游戏结束条件：
  1，阵营被击毁；
  1.1，NPC方阵营生命值归零，则被击毁， 玩家获胜
  1.2，玩家阵营生命值归零，则被击毁， 玩家失败
  2，玩家生命值归零；玩家失败 
  */
  //判断游戏是否结束
  function judgGameOver() {
    if (that.enemyCamp.life <= 0) {
      //清除页面所有定时器
      alert("游戏结束，白色阵营玩家获胜");
      clearInterval();
      // location.reload();
      clearAllInterval();
      return;
    }
    if (that.playerCamp.life <= 0) {
      //清除页面所有定时器
      alert("游戏结束，黑色阵营玩家获胜");
      clearInterval();
      // location.reload();
      clearAllInterval();
      return;
    }
    if (that.player.life <= 0) {
      //清除页面所有定时器
      alert("游戏结束，您的生命值为零，黑色阵营玩家获胜");
      // location.reload();
      clearAllInterval();
      return;
    }
  }
  function clearAllInterval() {
    for (let key in timerObj) {
      clearInterval(timerObj[key]);
    }
    clearInterval(enemyMoveTimer);
  }
  window.Game = Game;
})(window, undefined);
